package models

import (
	"bytes"
	"errors"
	"fmt"
	"strings"
	"time"

	"github.com/prometheus/common/log"
	"golang.org/x/crypto/ssh"
)

const (
	ROOT          = "root"
	LinuxName     = "root"
	LinuxPassword = "980131"
)

var (
	LinuxCache = make(map[string]*Linux)
	LinuxIps   = []string{
		"192.168.146.133",
		"192.168.146.134",
	}
)

type Linux struct {
	Ip       string `json:"ip"`
	Name     string `json:"name"`
	Password string `json:"password"`
	client   *ssh.Client
	lastTime time.Time
	// 当前所在目录
	Pkg string
}

func (linux *Linux) Login() error {
	_, ok := LinuxCache[linux.Ip]
	if ok {
		return errors.New(fmt.Sprintf("ip[%s] is logged in,please do not repeat the login", linux.Ip)) // 请勿重复登录
	}
	client, err := ssh.Dial("tcp", fmt.Sprintf("%s:22", linux.Ip), &ssh.ClientConfig{
		User: linux.Name,
		Auth: []ssh.AuthMethod{
			ssh.Password(linux.Password),
		},
		HostKeyCallback: ssh.InsecureIgnoreHostKey(),
	})
	if err != nil {
		return err
	}
	linux.client = client
	linux.lastTime = time.Now()
	linux.Pkg = "/root"
	LinuxCache[linux.Ip] = linux
	return nil
}

func (linux *Linux) Logout() error {
	err := linux.client.Close()
	if err != nil {
		log.Errorf("close client error: %v", err)
		return err
	}
	delete(LinuxCache, linux.Ip)
	return nil
}

func (linux *Linux) Timeout() (bool, error) {
	if time.Now().Sub(linux.lastTime) > 30*time.Minute {
		err := linux.client.Close()
		if err != nil {
			return false, err
		}
		return true, nil
	}
	return false, nil
}

func (linux *Linux) Exec(cmd string) ([]byte, error) {
	session, err := linux.client.NewSession()
	if err != nil {
		return nil, err
	}
	defer session.Close()
	var rightResult, errorResult []byte
	var stdout = bytes.NewBuffer(rightResult)
	var stderr = bytes.NewBuffer(errorResult)
	session.Stdout = stdout
	session.Stderr = stderr
	c := "cd " + linux.Pkg + ";" + cmd + ";echo;pwd"
	err = session.Run(c)
	if err != nil || stderr.String() != "" {
		return nil, errors.New(stderr.String())
	}
	res := stdout.String()
	resSplits := strings.Split(res, "\n")
	linux.Pkg = resSplits[len(resSplits)-2]
	res = res[:strings.LastIndex(res, "\n")]
	res = res[:strings.LastIndex(res, "\n")]
	return []byte(res), nil
}
